package com.wry.service.impl;

import com.wry.dto.AccountDeductedDTO;
import com.wry.dto.StockDeductedDTO;
import com.wry.entity.TOrder;
import com.wry.rpc.AccountRpcService;
import com.wry.rpc.StockRpcService;
import com.wry.service.OrderApiService;
import com.wry.service.TOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * <h1>  <h1>
 *
 * @author 魏如元
 * @since 2022/10/7
 */
@Service
@Slf4j
public class OrderApiServiceImpl implements OrderApiService {

    @Resource
    private TOrderService tOrderService;
    @Resource
    private AccountRpcService accountRpcService;
    @Resource
    private StockRpcService stockRpcService;
    @Resource
    private RedissonClient redissonClient;

    private final static String LOCK_KEY = "RESOURCE_KEY";

    /**
     * 最大等待时间
     */
    private final static Long MAX_WAIT_TIME = 300L;

    /**
     * 自动解锁时长
     */
    private final static Long AUTO_FREED_TIME = 50L;

    @Override
    @GlobalTransactional(name = "my_test_tx_group", rollbackFor = Exception.class)
    public void createOrder(TOrder tOrder) {
        final RLock lock = redissonClient.getLock(LOCK_KEY);
        try {
            if (lock.tryLock(MAX_WAIT_TIME, AUTO_FREED_TIME, TimeUnit.MILLISECONDS)) {
                log.info("线程:" + Thread.currentThread().getName() + "获得了锁");
                // 业务处理

                // 1.创建订单
                log.info("-----创建订单---start");
                tOrderService.save(tOrder);
                log.info("-----创建订单---end");

                // 2.扣减库存
                log.info("-----扣减库存---start");
                StockDeductedDTO stockDeductedDTO = new StockDeductedDTO();
                stockDeductedDTO.setCount(tOrder.getCount());
                stockDeductedDTO.setProductId(tOrder.getProductId());
                stockRpcService.deductedStock(stockDeductedDTO);
                log.info("-----扣减库存---end");

                // 3.扣减账户
                log.info("-----扣减账户---start");
                AccountDeductedDTO accountDeductedDTO = new AccountDeductedDTO();
                accountDeductedDTO.setMoney(tOrder.getMoney());
                accountDeductedDTO.setUserId(tOrder.getUserId());
                accountRpcService.deductedAccount(accountDeductedDTO);
                log.info("-----扣减账户---end");

                // 4.更新订单状态
                log.info("-----更新订单状态---start");
                updateOrderStatus(tOrder.getUserId());
                log.info("-----更新订单状态---end");

                log.info("SUCCESS");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("订单服务未知异常：{}", e.getMessage());
        } finally {
            log.info("线程:" + Thread.currentThread().getName() + "即将释放锁~");
            //释放锁
            lock.unlock();
        }
    }

    @Override
    public void updateOrderStatus(Long userId) {
        tOrderService.lambdaUpdate()
                .eq(TOrder::getUserId, userId)
                .set(TOrder::getStatus, 1)
                .update();
    }
}
